package com.xuexiang.xuidemo.db;

import ohos.app.Context;
import ohos.data.DatabaseHelper;
import ohos.data.orm.OrmContext;
import ohos.data.orm.OrmMigration;
import ohos.data.orm.OrmObject;
import ohos.data.orm.OrmPredicates;
import ohos.data.rdb.ValuesBucket;

import java.sql.Time;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * 数据库服务类
 *
 * @param <T>
 */
public class DBService<T extends OrmObject> {
    /**
     * 数据库操作Dao
     */
    private OrmContext mDao;
    /**
     * 数据库打开助手
     */
    private DatabaseHelper mSqliteOpenHelper;

    private Class<T> clazz;

    /**
     * 构造应用内部的数据库
     *
     * @param context 上下文
     * @param dbAlias 数据库别名
     * @param dbName 数据库名.db
     * @param databaseClazz 数据库表实体类型
     */
    public DBService(Context context, String dbAlias, String dbName, Class databaseClazz, OrmMigration ormMigration) {
        mSqliteOpenHelper = new DatabaseHelper(context);
        mDao = mSqliteOpenHelper.getOrmContext(dbAlias, dbName, databaseClazz);
    }

    /**
     * 初始化 获取数据库服务对象
     *
     * @param clazz 泛型对象
     * @return DBService对象
     */
    public DBService init(Class<T> clazz) {
        this.clazz = clazz;
        return this;
    }

    /************************************************* 插入 **********************************************/
    /**
     * 插入单条数据
     *
     * @param object
     * @return boolean
     */
    public boolean insert(T object) {
        mDao.insert(object);
        return mDao.flush();
    }


    /************************************************* 查询 **********************************************/

    /**
     * 查询所有的数据
     *
     * @return List<T>泛型数组
     */
    public List<T> queryAll() {
        return mDao.query(mDao.where(clazz));
    }

    /**
     * 查询所有的数据并根据列名（1个）进行排序，返回一个对象集合
     *
     * @param columnName 排序的列名
     * @param ascending true：升序，false：降序
     * @return List<T>泛型数组
     */
    public List<T> queryAllOrderBy(String columnName, boolean ascending) {
        OrmPredicates ormPredicates;
        if (ascending) {
            ormPredicates = mDao.where(clazz).orderByAsc(columnName);
        } else {
            ormPredicates = mDao.where(clazz).orderByDesc(columnName);
        }
        return mDao.query(ormPredicates);
    }

    /**
     * 查询所有的数据并根据列名（2个）进行排序，返回一个对象集合
     *
     * @param columnName1 排序的列名1
     * @param ascending1 true：升序，false：降序
     * @param columnName2 排序的列名2
     * @param ascending2 true：升序，false：降序
     * @return List<T> 泛型数组
     * @
     */
    public List<T> queryAllOrderBy(String columnName1, boolean ascending1, String columnName2, boolean ascending2) {
        OrmPredicates ormPredicates;
        if (ascending1) {
            ormPredicates = mDao.where(clazz).orderByAsc(columnName1);
        } else {
            ormPredicates = mDao.where(clazz).orderByDesc(columnName1);
        }
        ormPredicates = orderByAsc(ormPredicates, columnName2, ascending2);
        return mDao.query(ormPredicates);
    }

    /**
     * 有条件的排序查询，返回一个对象集合
     *
     * @param fieldName 查询条件列名
     * @param value 查询条件列名的值
     * @param columnName 排序的列名
     * @param ascending true：升序，false：降序
     * @return List<T>泛型数组
     * @
     */
    public List<T> queryAndOrderBy(String fieldName, Object value, String columnName, boolean ascending) {
        OrmPredicates ormPredicates = mDao.where(clazz);
        ormPredicates = equalTo(ormPredicates, fieldName, value);
        ormPredicates = orderByAsc(ormPredicates, columnName, ascending);
        return mDao.query(ormPredicates);
    }

    public List<T> queryAll(String columnName, Object value) {
        OrmPredicates ormPredicates = mDao.where(clazz);
        if (value instanceof String) {
            ormPredicates = ormPredicates.equalTo(columnName, (String) value);
        } else if (value instanceof Boolean) {
            ormPredicates = ormPredicates.equalTo(columnName, (boolean) value);
        } else if (value instanceof Byte) {
            ormPredicates = ormPredicates.equalTo(columnName, (byte) value);
        } else if (value instanceof Short) {
            ormPredicates = ormPredicates.equalTo(columnName, (short) value);
        } else if (value instanceof Float) {
            ormPredicates = ormPredicates.equalTo(columnName, (float) value);
        } else if (value instanceof Double) {
            ormPredicates = ormPredicates.equalTo(columnName, (double) value);
        } else if (value instanceof Long) {
            ormPredicates = ormPredicates.equalTo(columnName, (long) value);
        } else if (value instanceof Integer) {
            ormPredicates = ormPredicates.equalTo(columnName, (int) value);
        } else if (value instanceof Date) {
            ormPredicates = ormPredicates.equalTo(columnName, (Date) value);
        } else if (value instanceof Time) {
            ormPredicates = ormPredicates.equalTo(columnName, (Time) value);
        } else if (value instanceof Timestamp) {
            ormPredicates = ormPredicates.equalTo(columnName, (Timestamp) value);
        }
        return mDao.query(ormPredicates);
    }

    /**
     * 根据条件查询(一个条件) 返回第一个符合条件的对象
     *
     * @param columnName 查询条件列名
     * @param value 查询条件列名的值
     * @return 传递的泛型对象
     */
    public T queryForColumnFirst(String columnName, Object value) {
        List<T> list = queryAll(columnName, value);
        if (list == null || list.size() == 0) {
            return null;
        }
        return list.get(0);
    }

    /************************************************* 更新 **********************************************/
    /**
     * 使用对象更新一条记录（注意：对象必须带唯一标识ID,且该方法不能更新ID字段)
     *
     * @param object 更新的对象
     * @return boolean 是否更新
     */
    public boolean updateData(T object) {
        mDao.update(object);
        return mDao.flush();
    }

    /**
     * 根据某一条件更新对象的多列属性
     *
     * @param valuesBucket 更新列名和更新值的集合
     * @param columnName 更新条件列名
     * @param value 更新条件值
     * @return int 更新记录的数量
     */
    public int updateDataByColumn(ValuesBucket valuesBucket, String columnName, Object value) {
        OrmPredicates update = mDao.where(clazz);
        update = equalTo(update, columnName, value);
        return mDao.update(update, valuesBucket);
    }

    /************************************************* 删除 **********************************************/
    /**
     * 根据对象删除一条记录（注意：对象必须带唯一标识ID,否则方法不起作用)
     *
     * @param object 删除的对象
     * @return boolean是否删除
     */
    public boolean deleteData(T object) {
        mDao.delete(object);
        return mDao.flush();
    }

    /**
     * 删除所有数据
     *
     * @return boolean
     */
    public boolean deleteAll() {
        List<T> list = mDao.query(mDao.where(clazz));
        Iterator<T> it = list.iterator();
        while (it.hasNext()) {
            mDao.delete(it.next());
        }
        return mDao.flush();
    }

    // ========================其他操作===============================//

    /**
     * 获取数据库支持
     *
     * @return DatabaseHelper对象
     */
    public DatabaseHelper getSqliteOpenHelper() {
        return mSqliteOpenHelper;
    }

    private OrmPredicates equalTo(OrmPredicates ormPredicates, String fieldName, Object value) {
        if (value instanceof String) {
            ormPredicates = ormPredicates.equalTo(fieldName, (String) value);
        } else if (value instanceof Boolean) {
            ormPredicates = ormPredicates.equalTo(fieldName, (boolean) value);
        } else if (value instanceof Byte) {
            ormPredicates = ormPredicates.equalTo(fieldName, (byte) value);
        } else if (value instanceof Short) {
            ormPredicates = ormPredicates.equalTo(fieldName, (short) value);
        } else if (value instanceof Float) {
            ormPredicates = ormPredicates.equalTo(fieldName, (float) value);
        } else if (value instanceof Double) {
            ormPredicates = ormPredicates.equalTo(fieldName, (double) value);
        } else if (value instanceof Long) {
            ormPredicates = ormPredicates.equalTo(fieldName, (long) value);
        } else if (value instanceof Integer) {
            ormPredicates = ormPredicates.equalTo(fieldName, (int) value);
        } else if (value instanceof Date) {
            ormPredicates = ormPredicates.equalTo(fieldName, (Date) value);
        } else if (value instanceof Time) {
            ormPredicates = ormPredicates.equalTo(fieldName, (Time) value);
        } else if (value instanceof Timestamp) {
            ormPredicates = ormPredicates.equalTo(fieldName, (Timestamp) value);
        }
        return ormPredicates;
    }

    private OrmPredicates orderByAsc(OrmPredicates ormPredicates, String columnName, boolean asc) {
        if (asc) {
            ormPredicates = ormPredicates.orderByAsc(columnName);
        } else {
            ormPredicates = ormPredicates.orderByDesc(columnName);
        }
        return ormPredicates;
    }

}
